﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dexter.Domain.Model;
using Dexter.PluginManager;
using Dexter.Plugins.Linkflood;
using Dexter.Plugins.Linkflood.Helpers;
using Dexter.Plugins.Linkflood.Models;
using Dexter.Scheduler;
using Dexter.Services;
using Dexter.Web.Routing;
using Configuration = Dexter.Plugins.Linkflood.Configuration;

namespace Dexter.Plugins.SelectiveTwitter.Jobs {
	public class TwitterPosterJob : ICronJob {
		internal const string UNIQUE_ID = "fabc0563-a302-4c54-9d35-38174ce543b1";
		readonly Plugin selectiveTweerPlugin;
		readonly IPluginService pluginService;
		readonly IPageService pageService;
		readonly IRoutingService routingService;
		readonly IUrlBuilder urlBuilder;
		readonly Configuration configuration = ConfigurationHelper.GetConfiguration;

		public TwitterPosterJob(IPluginService pluginService, IPageService pageService, IRoutingService routingService, IUrlBuilder urlBuilder) {
			this.pluginService = pluginService;
			this.pageService = pageService;
			this.routingService = routingService;
			this.urlBuilder = urlBuilder;

			selectiveTweerPlugin = pluginService.GetPluginByUniqueKey(new Guid(Constants.PLUGIN_IDENTIFIER));

			if (selectiveTweerPlugin == null)
				throw new PluginException(Constants.PLUGIN_IDENTIFIER);
		}

		#region ICronJob Members

		public bool AutoManageSession {
			get { return true; }
		}

		public string GroupName {
			get { return "SelectiveTwitterPlugin"; }
		}

		public bool IsVolatile {
			get { return true; }
		}

		public void Execute() {
			var data = pluginService.RetrieveDataForSpecifiedDateRange(selectiveTweerPlugin, DateTime.Today, DateTime.Now, 1000, 0);

			if(data == null || !data.Result.Any())
				return;

			var tweets = data.Result.Select(x => x.Data.Deserialize<Tweet>());

			Dictionary<string, IList<Tweet>> groupedTweets = new Dictionary<string, IList<Tweet>>();

			foreach (var tweet in tweets) {
				var category = GetCategoryName(tweet);

				if (groupedTweets.ContainsKey(category)) {
					var tws = groupedTweets[category];
					tws.Add(tweet);

					groupedTweets.Remove(category);
					groupedTweets.Add(category,tws);
				}
				else {
					var tws = new List<Tweet>();
					tws.Add(tweet);
					groupedTweets.Add(category, tws);
				}
			}

			var sortedGroupTweet = groupedTweets.OrderBy(entry => entry.Key).ToDictionary(pair => pair.Key, pair => pair.Value);

			string pageTitle = string.Format(configuration.SubPageTitleFormat, DateTime.Today.ToString("dd-MMM-yyyy"));
			string pageTitleSlug = string.Format(configuration.SubPageSlugFormat, DateTime.Today.ToString("dd-MMM-yyyy"));

			StringBuilder body = new StringBuilder();
			body.AppendFormat("<h1>{0}</h1><br>", DateTime.Today.ToString("dd MMM yyyy"));

			foreach (var groupedTweet in sortedGroupTweet)
			{
				body.AppendFormat("<h2>{0} ({1})</h2><br />", groupedTweet.Key, groupedTweet.Value.Count);

				body.Append("<ul>");

				foreach (var tweet in groupedTweet.Value) {
					body.AppendFormat("<li>{0}</li>", ParseText(tweet.Text));
				}

				body.Append("</ul>");
			}

			var parentPage = this.pageService.GetBySlug(configuration.PageSlug);

			var p = Page.CreateNewPage(pageTitle, body.ToString(), pageTitleSlug);
			p.Parent = parentPage;
			p.Publish();
			p.PublishDate = DateTime.Now;

			parentPage.FormattedBody = UpdateParentPageBody(parentPage.FormattedBody, p);

			pageService.Save(p);
			pageService.Update(parentPage);

			routingService.UpdateRoutes();
		}

		public string UniqueId {
			get { return UNIQUE_ID; }
		}

		public string CronPatter {
			get {
				return @"0 35 16 1/1 * ? *";
				//return @"0 0 0 1/1 * ? *";
			}
		}

		#endregion

		string GetCategoryName(Tweet tweet) {
			foreach (var category in configuration.Categories) {
				if (category.HashTags.Any(hashTag => tweet.Text.Contains(hashTag))) {
					return category.CategoryName;
				}	
			}

			return "Misc";
		}

		string ParseText(string text) {
			text = ParserHelper.Linkify(text);
			text = ParserHelper.LinkifyHashtags(text);
			text = ParserHelper.LinkifyMentions(text);

			return text;
		}

		string UpdateParentPageBody(string body, Page newPage) {
			return body.Replace("</ul>", string.Format("<li><a href=\"{1}\">{0}</a></li></ul>", DateTime.Today.ToString("dd - MMM - yyyy"),urlBuilder.Page.Detail(newPage)));
		}
	}
}